﻿
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using Jade.Tools.SL.Windows.Extensions;
using JulMar.Silverlight.Interfaces;
using JulMar.Silverlight.Mvvm;
using JulMar.Siverlight.Helpers.Interactivity;
using MediaBrowserSL.RIA.MediaBrowserServiceReference;
using MediaBrowserSL.RIA.MvvmUtils;
using MediaBrowserSL.RIA.MvvmUtils.UI;
using MediaBrowserSL.RIA.Services;
using MediaBrowserSL.RIA.Tools;
using System.ServiceModel;

namespace MediaBrowserSL.RIA.ViewModels
{
    /// <summary>
    /// Pictures View Model
    /// </summary>
    public class PagePicturesViewModel : PageViewModelBase
    {
        #region Private Member

        private IErrorVisualizer errorVisualizer;
        private Dictionary<Media, FileInfo> listDropItem;
        private bool mediaItemCreating;
        private bool isDroping;
        private ICustomMessageBoxVisualizer customMessageBoxVisualizer;
        private IWindowZoomPictureVisualizer windowZoomPictureVisualizer;
        private bool isSaving;
        private Media newMedia;
        private DispatcherTimer testSelectedItemTimer;
        private bool isFullException;

        #endregion

        #region Public Properties

        public override string Name
        {
            get { return "Page Pictures"; }
        }

        public bool IsDroping
        {
            get
            {
                return this.isDroping;
            }
            set
            {
                this.isDroping = value;
                OnPropertyChanged("IsDroping");
            }
        }

        public bool IsSaving
        {
            get
            {
                return isSaving;
            }
            set
            {

                isSaving = value;
                OnPropertyChanged("IsSaving");
            }
        }

        public Media NewMedia
        {
            get
            {
                return newMedia;
            }
            set
            {

                newMedia = value;
                OnPropertyChanged("NewMedia");
            }
        }

        #endregion

        #region Command

        public ICommand DropItemCommand
        {
            get;
            private set;
        }

        public ICommand DeleteItemCommand
        {
            get;
            private set;
        }

        public ICommand ViewItemCommand
        {
            get;
            private set;
        }

        public ICommand GoToBackCommand
        {
            get;
            private set;
        }

        public ICommand GoToFrontCommand
        {
            get;
            private set;
        }

        public DelegatingCommand AddFolderCommand
        {
            get;
            private set;
        }

        public DelegatingCommand UpdateFolderCommand
        {
            get;
            private set;
        }

        public DelegatingCommand DeleteFolderCommand
        {
            get;
            private set;
        }



        #endregion

        public PagePicturesViewModel(IMediaRiaServices service)
            : base(service)
        {
            errorVisualizer = Resolve<IErrorVisualizer>();
            customMessageBoxVisualizer = Resolve<ICustomMessageBoxVisualizer>();
            windowZoomPictureVisualizer = Resolve<IWindowZoomPictureVisualizer>();

            DropItemCommand = new DelegatingCommand<EventInformation>(DropItem);
            DeleteItemCommand = new DelegatingCommand<EventInformation>(DeleteItem);
            ViewItemCommand = new DelegatingCommand(ViewItem);
            GoToBackCommand = new DelegatingCommand(GoToBack);
            GoToFrontCommand = new DelegatingCommand(GoToFront);

            AddFolderCommand = new DelegatingCommand(AddFolder);
            UpdateFolderCommand = new DelegatingCommand(UpdateFolder);
            DeleteFolderCommand = new DelegatingCommand(DeleteFolder);

            listDropItem = new Dictionary<Media, FileInfo>();

            NewMedia = new Media();

            testSelectedItemTimer = new DispatcherTimer();
            testSelectedItemTimer.Interval = new TimeSpan(0, 0, 0, 0, 100);
            testSelectedItemTimer.Tick += testSelectedItemTimer_Tick;

        }

        #region private Methods

        #region GetListMediasByCategory

        /// <summary>
        /// Return Medias
        /// </summary>
        /// <param name="movies"></param>
        private void GetListMediasByCategory(IEnumerable<Media> pictures, Exception ex)
        {
            if (ex == null)
            {
                if (pictures != null)
                {
                    if (medias != null) { medias.Clear(); } else { medias = new ObservableCollection<Media>(); }
                    foreach (var m in pictures)
                    {
                        medias.Add(m);
                    }
                    sourceMediasView.Source = medias;
                    sourceMediasView.View.CurrentChanged += View_CurrentChanged;
                    OnPropertyChanged("MediasView");
                    SelectedItem = null;
                }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        void View_CurrentChanged(object sender, EventArgs e)
        {
            if (CurrentMedia != null)
            {
                if (CurrentMedia.MediaItems == null) { CurrentMedia.MediaItems = new ObservableCollection<Media>(); }
                mediaItems = new ObservableCollection<Media>(CurrentMedia.MediaItems);
                sourceMediaItemsView.Source = mediaItems;
                sourceMediaItemsView.View.CurrentChanged += mediaItemsView_CurrentChanged;

                //Drap Drop Media
                if (CurrentMedia.MediaItems.Count == 0)
                {
                    Media m = new Media() { Id = -1, Name = "DrapDrop", Description = "DrapDrop", UrlImage = "/MediaBrowserSL.RIA;component/Images/DragDrop.png", CreationDate = DateTime.Now };
                    m.Category = new Category() { Id = 3 };
                    CurrentMedia.MediaItems.Add(m);
                    mediaItems.Add(m);
                }

                NewMedia.Name = CurrentMedia.Name;

                lastMediaSelected = CurrentMedia;
                testSelectedItemTimer.Stop();
                testSelectedItemTimer.Start();

                OnPropertyChanged("CurrentMedia");
                OnPropertyChanged("MediaItemsView");
                OnPropertyChanged("NewMedia");
            }
        }

        void testSelectedItemTimer_Tick(object sender, EventArgs e)
        {
            testSelectedItemTimer.Stop();
            if (CurrentMedia == null)
            {
                sourceMediasView.View.CurrentChanged -= View_CurrentChanged;
                MediasView.MoveCurrentTo(lastMediaSelected);
                sourceMediasView.View.CurrentChanged += View_CurrentChanged;
            }
        }

        void mediaItemsView_CurrentChanged(object sender, EventArgs e)
        {
            OnPropertyChanged("CurrentMediaItem");
        }

        #endregion

        #region Drop/Create Picture

        /// <summary>
        /// Drop new item
        /// Set All Item into List and process in a thread
        /// </summary>
        /// <param name="e"></param>
        private void DropItem(EventInformation e)
        {
            if (!isDroping)
            {
                if (CurrentMedia != null)
                {
                    DragEventArgs de = e.EventParameter as DragEventArgs;

                    if ((de.Data != null) && (de.Data.GetDataPresent(DataFormats.FileDrop)))
                    {
                        FileInfo[] files = de.Data.GetData(DataFormats.FileDrop) as FileInfo[];

                        if (files != null)
                        {
                            listDropItem.Clear();
                            for (int i = 0; i <= files.Length - 1; i++)
                            {
                                FileInfo f = files[i];
                                if (f.Name.IsImageFile())
                                {
                                    Media mediaItem = new Media() { Name = Path.GetFileNameWithoutExtension(f.Name), Description = f.Name, UrlImage = f.Name, CreationDate = DateTime.Now };
                                    mediaItem.Category = new Category() { Id = 3 };
                                    listDropItem.Add(mediaItem, f);
                                }
                            }

                            //Asynchrone Process
                            Thread th = new Thread(new ThreadStart(ProcessDropListItem));
                            th.Start();
                            IsDroping = true;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Create All Media from listDropItem
        /// </summary>
        private void ProcessDropListItem()
        {
            foreach (KeyValuePair<Media, FileInfo> item in listDropItem)
            {
                mediaItemCreating = true;
                Deployment.Current.Dispatcher.BeginInvoke(delegate
                {
                    service.CreateMediaItem(MediaItemCreated, item.Key, CurrentMedia, SessionMb.CurrentUser, item.Value, null);
                });

                //waiting Create Media Item
                while (mediaItemCreating) { Thread.Sleep(10); }

                if (isFullException)
                {
                    isFullException = false;
                    break;
                }
            }

            Deployment.Current.Dispatcher.BeginInvoke(delegate
            {
                IsDroping = false;
                //Delete Drap Drop Picture if exist
                var md = (from m in mediaItems where m.Id == -1 select m).SingleOrDefault();
                if (md != null) { CurrentMedia.MediaItems.Remove(md); mediaItems.Remove(md); }
            });
        }

        /// <summary>
        /// Media Item Created
        /// </summary>
        /// <param name="m"></param>
        /// <param name="ex"></param>
        private void MediaItemCreated(Media m, Exception ex)
        {
            mediaItemCreating = false;
            if (ex == null)
            {
                CurrentMedia.MediaItems.Add(m);
                mediaItems.Add(m);
            }
            else if (ex.GetType().Equals(typeof(FullServerException)))
            {
                isFullException = true;
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null,
                                                        "Votre espace serveur est plein !",
                                                        "Espace indisponible",
                                                        MessageBoxButton.OK,
                                                        MessageBoxImage.Error);
                }

            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        #endregion

        #region Delete Picture

        private void DeleteItem(EventInformation e)
        {
            if (!isDroping)
            {
                if (CurrentMediaItem != null)
                {
                    if (CurrentMediaItem.Id != -1)
                    {
                        KeyEventArgs ev = e.EventParameter as KeyEventArgs;

                        if (ev.Key == Key.Delete)
                        {
                            if (customMessageBoxVisualizer != null)
                            {
                                customMessageBoxVisualizer.Show(ConfirmDeletePicture, "Etes-vous sur de vouloir supprimer cette image ?", "Supprimer", MessageBoxButton.OKCancel, MessageBoxImage.Question);
                            }
                            else
                            {
                                service.DeleteMedia(PictureDeleted, CurrentMediaItem, SessionMb.CurrentUser);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Confirm Delete Picture
        /// </summary>
        /// <param name="r"></param>
        private void ConfirmDeletePicture(MessageBoxResult r)
        {
            if (r == MessageBoxResult.OK)
            {
                service.DeleteMedia(PictureDeleted, CurrentMediaItem, SessionMb.CurrentUser);
            }
        }

        /// <summary>
        /// Picture Deleted
        /// </summary>
        /// <param name="e"></param>
        private void PictureDeleted(Exception ex)
        {
            if (ex == null)
            {
                if (CurrentMedia != null) { CurrentMedia.MediaItems.Remove(CurrentMediaItem); }
                if (mediaItems != null) { mediaItems.Remove(CurrentMediaItem); }

                //Drap Drop Media
                if (CurrentMedia.MediaItems.Count == 0)
                {
                    Media m = new Media() { Id = -1, Name = "DrapDrop", Description = "DrapDrop", UrlImage = "/MediaBrowserSL.RIA;component/Images/DragDrop.png", CreationDate = DateTime.Now };
                    m.Category = new Category() { Id = 3 };
                    CurrentMedia.MediaItems.Add(m);
                    mediaItems.Add(m);
                }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        #endregion

        #region Zoom Picture

        /// <summary>
        /// View Zoom Item
        /// </summary>
        private void ViewItem()
        {
            if (windowZoomPictureVisualizer != null)
            {
                if ((CurrentMediaItem != null) && (CurrentMediaItem.Id != -1))
                {
                    windowZoomPictureVisualizer.Show(CloseZoomPicture);
                }
            }
        }

        private void CloseZoomPicture(object sender)
        {
            service.UpdateMedia(OnPictureUpdated, CurrentMediaItem);
        }

        /// <summary>
        /// On Picture Updated
        /// </summary>
        /// <param name="Media"></param>
        /// <param name="ex"></param>
        private void OnPictureUpdated(Exception ex)
        {
            if (ex != null)
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        #endregion

        #region Add/Update/Remove Folder

        /// <summary>
        /// Add Folder
        /// </summary>
        private void AddFolder()
        {
            if (NewMedia != null) { NewMedia.Name = "New Folder"; }

            Media m = new Media() { Name = NewMedia.Name, Description = NewMedia.Name, CreationDate = DateTime.Now };
            m.Category = new Category() { Id = 3 };
            IsSaving = true;
            service.CreateMedia(OnFolderCreated, m, SessionMb.CurrentUser, null, null);
        }

        /// <summary>
        /// On Folder Created
        /// </summary>
        /// <param name="Media"></param>
        /// <param name="ex"></param>
        private void OnFolderCreated(Media m, Exception ex)
        {
            IsSaving = false;
            if (ex == null)
            {
                medias.Add(m);
            }
            else if (ex.GetType().Equals(typeof(FullServerException)))
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null,
                                                        "Votre espace serveur est plein !",
                                                        "Espace indisponible",
                                                        MessageBoxButton.OK,
                                                        MessageBoxImage.Error);
                }

            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        /// <summary>
        /// Update Folder
        /// </summary>
        private void UpdateFolder()
        {
            if (!String.IsNullOrEmpty(NewMedia.Name))
            {
                if (CurrentMedia != null)
                {
                    IsSaving = true;
                    CurrentMedia.Name = NewMedia.Name; CurrentMedia.Description = NewMedia.Description;
                    service.UpdateMedia(OnFolderUpdated, CurrentMedia);
                }
            }
        }

        /// <summary>
        /// On Folder Updated
        /// </summary>
        /// <param name="ex"></param>
        private void OnFolderUpdated(Exception ex)
        {
            IsSaving = false;
            if (ex != null)
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        /// <summary>
        /// Delete Folder
        /// </summary>
        private void DeleteFolder()
        {
            if (CurrentMedia != null)
            {
                if (!IsSaving)
                {
                    if ((mediaItems == null) || (mediaItems.Count == 0) || mediaItems[0].Id == -1)
                    {
                        if (customMessageBoxVisualizer != null)
                        {
                            customMessageBoxVisualizer.Show(ConfirmDeleteFolder, "Etes-vous sur de vouloir supprimer ce dossier ?", "Supprimer", MessageBoxButton.OKCancel, MessageBoxImage.Question);
                        }
                        else
                        {
                            IsSaving = true;
                            service.DeleteMedia(FolderDeleted, CurrentMedia, SessionMb.CurrentUser);
                        }
                    }
                    else
                    {
                        if (customMessageBoxVisualizer != null)
                        {
                            customMessageBoxVisualizer.Show(null, "Vous devez d'abord supprimer toutes les images liées à ce dossier !", "Supprimer", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Confirm Delete Folder
        /// </summary>
        /// <param name="r"></param>
        private void ConfirmDeleteFolder(MessageBoxResult r)
        {
            if (r == MessageBoxResult.OK)
            {
                IsSaving = true;
                service.DeleteMedia(FolderDeleted, CurrentMedia, SessionMb.CurrentUser);
            }
        }

        /// <summary>
        /// Folder Deleted
        /// </summary>
        /// <param name="e"></param>
        private void FolderDeleted(Exception ex)
        {
            IsSaving = false;
            if (ex == null)
            {
                if (CurrentMedia != null) { mediaItems.Clear(); medias.Remove(CurrentMedia); }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        #endregion

        #region Rotate Windows Zoom Picture

        private void GoToBack()
        {
            if (windowZoomPictureVisualizer != null)
            {
                windowZoomPictureVisualizer.GoToBack();
            }
        }

        private void GoToFront()
        {
            if (windowZoomPictureVisualizer != null)
            {
                windowZoomPictureVisualizer.GoToFront();
            }
        }

        #endregion

        #endregion

        #region Public Methods

        /// <summary>
        /// Update Current User
        /// </summary>
        /// <param name="page"></param>
        [MessageMediatorTarget(MediatorMessages.UpdateCurrentUser)]
        public void UpdateCurrentUser(User user)
        {
            service.GetListMediasByCategory(GetListMediasByCategory, SessionMb.CurrentUser.Id, 3);
        }

        /// <summary>
        /// LogOut
        /// </summary>
        [MessageMediatorTarget(MediatorMessages.LogOut)]
        public void LogOut(User user)
        {
            if (medias != null)
            {
                if (sourceMediaItemsView.Source != null)
                {
                    (sourceMediaItemsView.Source as ObservableCollection<Media>).Clear();
                }
                medias.Clear();
                MediaLookFor = String.Empty;
                NewMedia = new Media();
                OnPropertyChanged("CurrentMedia");
                OnPropertyChanged("NewMedia");
            }
            else
            {
                medias = new ObservableCollection<Media>();
            }
        }

        #endregion

    }
}
